﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;


namespace Marmat.Forms
{
    public partial class DataGrid : ISupportInitialize
    {

        /// <summary>
        /// 是否开启了 CurrentChangedEvent 监听事件。
        /// </summary>
        private bool open_currentChangedEvent = true;
        /// <summary>
        /// 开启 CurrentChangedEvent 监听事件。
        /// </summary>
        protected void OpenCurrentChangedEvent()
        {
            this.open_currentChangedEvent = true;
        }

        /// <summary>
        /// 关闭 CurrentChangedEvent 监听事件。
        /// </summary>
        protected void CloseCurrentChangedEvent()
        {
            this.open_currentChangedEvent = false;
        }

        /// <summary>
        /// 提交自上次调用 System.Data.DataTable.AcceptChanges 以来对该表进行的所有更改。
        /// </summary>
        /// <remarks></remarks>
        public void AcceptChanges()
        {
            this.DataSource.AcceptChanges();
        }

        /// <summary>
        /// 在 DataGrid 中增加一行，并返回所增加的行。
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public Views.DataGrid.Row AddNew()
        {
            return this.AddNew(1);
        }

        /// <summary>
        /// 在 DataGrid 中增加一行或多行，并返回所增加的第一行。
        /// </summary>
        /// <param name="Count">要增加的行数，如果省略，则只增加一行。</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public Views.DataGrid.Row AddNew(int Count)
        {
            var dr = this.Rows.AddNew(Count);
            return dr;
        }

        /// <summary>
        /// 增加自定义样式。
        /// </summary>
        /// <param name="Name">样式名称</param>
        /// <param name="BackColor">背景颜色</param>
        /// <param name="ForeColor">字体颜色</param>
        /// <remarks></remarks>
        [Obsolete("正在考虑是否需要这个方法,所以尚未实现。")]
        private void AddUserStyle(string Name, Color BackColor, Color ForeColor)
        {
        }


        /// <summary>
        /// 根据指定的表达式和条件进行计算。
        /// </summary>
        /// <param name="Expression">要计算的表达式，使用聚合函数进行统计。</param>
        /// <remarks></remarks>
        public object Compute(string Expression)
        {
            return this.Compute(Expression, null);
        }

        /// <summary>
        /// 根据指定的表达式和条件进行计算。
        /// </summary>
        /// <param name="Expression">要计算的表达式，使用聚合函数进行统计。</param>
        /// <param name="Filter">可选参数，用于设置计算条件。</param>
        /// <remarks></remarks>
        public object Compute(string Expression, string Filter = null)
        {
            object result = null;
            result = this.DataSource.Compute(Expression, Filter);
            if (ReferenceEquals(result, DBNull.Value))
            {
                result = null;
            }

            return result;
        }

        /// <summary>
        /// 将 DataTable 的值填入到表格组件中。
        /// </summary>
        /// <param name="data"></param>
        public new void Load(DataTable data)
        {
            try
            {
                this.DataSource.BeginLoadData();
                this.DataSource.Clear();
                this.DataSource.Load(data.CreateDataReader());
                this.DataSource.AcceptChanges();
            }
            finally
            {
                this.DataSource.EndLoadData();
            }
        }


        /// <summary>
        /// 追载新数据
        /// </summary>
        /// <param name="data"></param>
        /// <remarks></remarks>
        public void AppendLoad(DataTable data)
        {
            try
            {
                this.DataSource.BeginLoadData();
                this.DataSource.Load(data.CreateDataReader());
                this.DataSource.AcceptChanges();
            }
            finally
            {
                this.DataSource.EndLoadData();
            }
        }

        /// <summary>
        /// 在DataTable查找符合条件的行，如果找到的话，返回找到的行，否则返回Nothing。
        /// </summary>
        /// <param name="Expression">查找条件表达式</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public Views.DataGrid.Row FindRow(string Expression)
        {
            return this.FindRow(Expression, "", 0);
        }

        /// <summary>
        /// 在DataTable查找符合条件的行，如果找到的话，返回找到的行，否则返回Nothing。
        /// </summary>
        /// <param name="Expression">查找条件表达式</param>
        /// <param name="Sort">指定排序方式</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public Views.DataGrid.Row FindRow(string Expression, string Sort)
        {
            return this.FindRow(Expression, Sort, 0);
        }

        /// <summary>
        /// 在DataTable查找符合条件的行，如果找到的话，返回找到的行，否则返回Nothing。
        /// </summary>
        /// <param name="Expression">查找条件表达式</param>
        /// <param name="Sort">指定排序方式</param>
        /// <param name="Index">指定返回第几个符合条件的行，0表示第一行</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public Views.DataGrid.Row FindRow(string Expression, string Sort, int Index)
        {
            var drs = this.DataSource.Select(Expression, Sort, DataViewRowState.CurrentRows);
            if (drs.Length > 0 && drs.Length > Index)
            {
                return new Views.DataGrid.Row(this, drs[Index]);
            }

            return null;
        }

        /// <summary>
        /// 以集合的形式，返回所有符合指定条件的行。
        /// </summary>
        /// <param name="Filter">条件表达式</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public List<Views.DataGrid.Row> Select(string Filter)
        {
            var list = this.Select(Filter, null, DataViewRowState.CurrentRows);
            return list;
        }

        /// <summary>
        /// 以集合的形式，返回所有符合指定条件的行。
        /// </summary>
        /// <param name="Filter">条件表达式</param>
        /// <param name="Sort">排序方式</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public List<Views.DataGrid.Row> Select(string Filter, string Sort)
        {
            var list = this.Select(Filter, Sort, DataViewRowState.CurrentRows);
            return list;
        }

        /// <summary>
        /// 以集合的形式，返回所有符合指定条件的行。
        /// </summary>
        /// <param name="Filter">条件表达式</param>
        /// <param name="Sort">排序方式</param>
        /// <param name="DataViewRowState">System.Data.DataViewRowState 值之一。</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public List<Views.DataGrid.Row> Select(string Filter, string Sort, DataViewRowState DataViewRowState)
        {
            var list = new List<Views.DataGrid.Row>();
            var drs = this.DataSource.Select(Filter, Sort, DataViewRowState);
            foreach (DataRow r in drs)
            {
                var dr = new Views.DataGrid.Row(this, r);
                list.Add(dr);
            }

            return list;
        }

        /// <summary>
        /// 撤销自打开文件或最近一次保存以来，对该表做出的修改。
        /// </summary>
        /// <remarks></remarks>
        public void RejectChanges()
        {
            this.DataSource.RejectChanges();
        }

        public override void BeginInit()
        {
            base.BeginInit();
        }

        public override void EndInit()
        {
            this.Sort = this.Sort;
            if (this.DesignMode == false)
            {
                foreach (Views.DataGrid.Column dc in this.Columns)
                {
                    if (dc.IsTemporary && !string.IsNullOrEmpty(dc.Expression) && dc.DataColumn is object)
                    {
                        dc.DataColumn.Expression = dc.Expression;
                    }
                    else if (dc.IsTemporary == false && !string.IsNullOrEmpty(dc.Expression))
                    {
                        System.Windows.Forms.MessageBox.Show("只有表达式列或者通过代码增加的临时列，才可以设置Expression属性。");
                    }
                }
            }

            base.EndInit();
        }

        /// <summary>
        /// 从指定列中，获取不重复的值，以集合的形式返回。
        /// </summary>
        /// <param name="ColumnName"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public List<string> GetValues(string ColumnName)
        {
            return this.GetValues(ColumnName, null, null);
        }

        /// <summary>
        /// 从指定列中，获取不重复的值，以集合的形式返回。
        /// </summary>
        /// <param name="ColumnName"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public List<string> GetValues(string ColumnName, string Filter)
        {
            return this.GetValues(ColumnName, Filter, null);
        }

        /// <summary>
        /// 从指定列中，获取不重复的值，以集合的形式返回。
        /// </summary>
        /// <param name="ColumnName"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public List<string> GetValues(string ColumnName, string Filter, string Sort)
        {
            var list = new List<string>();
            foreach (DataRow dr in this.DataSource.Select(Filter, Sort))
            {
                if (!string.IsNullOrEmpty(dr[ColumnName].ToString()) && !list.Contains(dr[ColumnName].ToString()))
                {
                    list.Add(dr[ColumnName].ToString());
                }
            }

            return list;
        }

        public new void RaiseCurrentChanged()
        {
            var Args = new Views.DataGrid.GridEventArgs(this);
            CurrentChanged?.Invoke(this, Args);
        }

        internal void RaiseEventBeforeAddDataRow(Views.DataGrid.DataGridCancelEventArgs e)
        {
            BeforeAddDataRow?.Invoke(this, e);
        }

        internal void RaiseEventDataRowAdding(Views.DataGrid.DataRowEventArgs e)
        {
            DataRowAdding?.Invoke(this, e);
        }

        internal void RaiseEventDataRowAdded(Views.DataGrid.DataRowEventArgs e)
        {
            DataRowAdded?.Invoke(this, e);
        }

        internal void RaiseEventBeforeDeleteDataRow(Views.DataGrid.DataRowCancelEventArgs e)
        {
            BeforeDeleteDataRow?.Invoke(this, e);
        }

        /// <summary>
        /// 正在删除一行的时候执行，这时行还未被删除。
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        internal void RaiseEventDataRowDeleting(Views.DataGrid.DataRowEventArgs e)
        {
            DataRowDeleting?.Invoke(this, e);
        }

        /// <summary>
        /// "删除行后执行，此时行已经被删除。
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        internal void RaiseEventDataRowDeleted(Views.DataGrid.DataRowEventArgs e)
        {
            DataRowDeleted?.Invoke(this, e);
        }
    }
}